package net.es.oscars.coord.test;

import net.es.oscars.coord.req.CoordRequest;
import net.es.oscars.coord.events.CoordEvent;
import net.es.oscars.coord.events.CoordEventListener;
import net.es.oscars.coord.actions.CoordAction;
import net.es.oscars.coord.actions.LockAction;
import net.es.oscars.coord.actions.UnLockAction;

public class LockActionOne extends CoordRequest <String,Object > {

    public static final String HELLO_EVENT_ONE="LockTestHelloEventOne";
    public static final String HELLO_EVENT_TWO="LockTestHelloEventTwo";
    public static final String REQUESTED_LOCK_EVENT="RequestLockEvent";
    
    private static final long       serialVersionUID  = 1L;
    private String lockName = null;
 
    public class ReleaseLock extends CoordAction <String, Object> implements CoordEventListener {
        private static final long serialVersionUID = 1L;
        private boolean discoveredPeer = false;
        
        private CoordEvent helloEvent = null;
        private CoordEvent requestEvent = null;
        
        
        public ReleaseLock (CoordRequest<String, Object> request, String lockName) {
            super ("ReleaseLock-1", request,lockName);
            // Register itself as a listener to the HELLO event generated by the the peer (two)
            // Note that the a reference to the event object must be kepts othewise the event may be GC'ed
            this.helloEvent = CoordEvent.getCoordEvent(LockActionOne.HELLO_EVENT_TWO);
            this.helloEvent.addListener(this);
            // Register itself as a listener to the REQUESTED_LOCK_EVENT
            this.requestEvent = CoordEvent.getCoordEvent(LockActionOne.REQUESTED_LOCK_EVENT);
            this.requestEvent.addListener(this);
        }
        
        public void execute () {
            // Send HELLO event.
            CoordEvent.getCoordEvent(LockActionOne.HELLO_EVENT_ONE).trigger();
        }
        
        public void handleEvent(CoordEvent event) {
            if (event.getName() == LockActionOne.HELLO_EVENT_TWO) {
                // This is a notification from the LockActionTwo. 
                if (this.discoveredPeer) {
                    // We already know about it. Ignore
                    return;
                }
                // Send HELLO_BACK
                this.discoveredPeer = true;
                CoordEvent.getCoordEvent(LockActionOne.HELLO_EVENT_ONE).trigger();
            } else if (event.getName() == LockActionOne.REQUESTED_LOCK_EVENT) {
                // Our peer is sending this event because it has requested the lock. Time to release it.
                // This action is completed
                this.executed();
            }
        }        
    }
    
    public LockActionOne (String name, String lockName) {
        super ("LockActionOne-1");
        this.lockName = lockName;
    }

    public LockActionOne(String gri, String name, String lockName) {
        super (gri, "LoclActionOne-1");
        this.lockName = lockName;
    }
    
    public void execute() {

        //---- Create the various actions of this request.
        // Request to acquire the lock.
        LockAction lockAction = new LockAction (this, "LockAction-1", this.lockName);
        this.add (lockAction);
        // Wait for the peer to be ready to synchronize with the lock
        ReleaseLock releaseLock = new ReleaseLock (this, "ReleaseLock-1");
        // Add it after the lockAction
        lockAction.add(releaseLock);
        // Add UnLockAction
        UnLockAction unlockAction = new UnLockAction (this, "UnLock-1", this.lockName);
        releaseLock.add(unlockAction);
        
        // Start the LockActionTwo
        LockActionTwo lockActionTwo = new LockActionTwo ("LockActionTwo-2", this.lockName);
        lockActionTwo.process();
        
        this.process();
        // This action is completed
        this.executed();
    }
    
    
}
